﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using Jb.Web.ViewModels;
using Jb.Domain;
using Jb.Web.Utility;
using AutoMapper;
using Jb.Common.Authentication;
using Jb.Common.Extensions;


namespace Jb.Web.Controllers
{
    public class AccountController : BaseController
    {
        private JbEntities _Context;
        
        public AccountController()
        {
            _Context = new JbEntities();
        }

        public AccountController(UserViewModel currentUser)
            : base(currentUser)
        {
            _Context = new JbEntities();
        }
        
        #region Action Methods

        public ActionResult LogOn(String returnUrl, String type = null)
        {
            if (SessionCache.CurrentUser != null)
            {
                //FIXME: Was creating redundent loop, if a jobseeker trys to enter into a Employer Page
                //if (!returnUrl.IsNullOrEmpty() && Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 
                //    && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                //{
                //    return Redirect(returnUrl);
                //}
                //FormsAuthentication.RedirectFromLoginPage(SessionCache.CurrentUser.UserName, true);
            }
            ///If redirected from Admin/Private area then redirect properly it to the employer login page.
            if (!returnUrl.IsNullOrEmpty())
            {                
                if ( type.IsNullOrEmpty() && (returnUrl.ToLower().StartsWith("/private") || returnUrl.ToLower().StartsWith("/admin")))
                {
                    if(returnUrl.ToLower().StartsWith("/private"))
                        returnUrl = String.Format("/account/logon?type=e&ReturnUrl={0}", returnUrl);
                    else if(returnUrl.ToLower().StartsWith("/admin"))
                        returnUrl = String.Format("/account/logon?type=a&ReturnUrl={0}", returnUrl);
                    return Redirect(returnUrl);
                }
            }
            return View();
        }

        /// <summary>
        /// Verifies the User Credential and Builds User Session if a Successfull attempt.
        /// Otherwise gives relevent info about un-successfull login attempt.
        /// </summary>
        /// <param name="model"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, String returnUrl)
        {
            if (ModelState.IsValid)
            {
                User user = _Context.Users.Include("Contact").Include("JobSeeker").Include("Group")
                    .FirstOrDefault(P => String.Compare(P.UserName, model.UserName, true) == 0 && String.Compare(P.Password, model.Password, true) == 0);
                if(user == null)
                    ModelState.AddModelError(AppConstants.Validation.INVALID_USER, "Sorry! The user name or password provided is incorrect.");
                else if(!user.IsActive)
                    ModelState.AddModelError(AppConstants.Validation.INVALID_USER, "Sorry! The user is currently inactive.");
                else
                {
                    if(user.Contact != null && !user.Contact.Company.IsActive)
                        ModelState.AddModelError(AppConstants.Validation.INVALID_USER, String.Format("Sorry! The company is not longer active in {0}.", ConfigReader.SiteName));
                    else if (user.JobSeeker != null && !user.JobSeeker.IsActive)
                        ModelState.AddModelError(AppConstants.Validation.INVALID_USER, String.Format("Sorry! The Job Seeker account has not activated yet in {0}. Please check your email for activation link.", ConfigReader.SiteName));
                    else
                    {
                        UserViewModel userViewModel = null;
                        userViewModel = Mapper.Map<User, UserViewModel>(user, userViewModel);
                        SessionCache.CurrentUser = userViewModel;
                        SessionCache.RefreshUserInfo();
                        ///Set the Authentication Token
                        FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                        ///Update the last login time for this user
                        user.LastLoggedIn = DateTime.Now;
                        _Context.SaveChanges();
                        //FormsAuthenticationUtil.RedirectFromLoginPage(model.UserName, userViewModel.Group.Name, model.RememberMe);

                        if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                            && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                        {
                            return Redirect(returnUrl);
                        }
                        else if(!SessionCache.RedirectUrl.IsEmpty())
                        {
                            ///Curretly this session contains only Job Apply Link. So checking for Job Seeker Only
                            if (UserInfo.IsJobSeeker)
                            {
                                returnUrl = SessionCache.RedirectUrl;
                                SessionCache.RedirectUrl = null;
                                return Redirect(returnUrl);
                            }
                            FormsAuthentication.RedirectFromLoginPage(model.UserName, model.RememberMe);
                        }
                        else
                            FormsAuthentication.RedirectFromLoginPage(model.UserName, model.RememberMe);
                    }
                }
            }
            // If we got this far, something failed, redisplay form
            return View(model);
        }

        /// <summary>
        /// Sign Out a user Gracefully from the system
        /// </summary>
        /// <returns></returns>
        public ActionResult LogOff()
        {
            String type = String.Empty;
            if (UserInfo.IsCompanyUser)
                type = "e";
            else if (UserInfo.IsAdmin)
                type = "a";
            SessionCache.ClearSession();
            FormsAuthentication.SignOut();
            return RedirectToAction("Logon", "Account", new { type = type });
            //return View("LogOn");
        }

        
        //public ActionResult Register(String msg = "")
        //{
        //    ViewBag.IsRegistrationSuccess = msg.IsEmpty() ? null : msg;
        //    return View();
        //}

        //[HttpPost]
        //public ActionResult Register(RegisterModel model)
        //{
        //    if (ModelState.IsValid)
        //    {
        //        if (_Context.IsDuplicateEmail(model.Email))
        //            ModelState.AddModelError("", "The Email address is already taken. Please choose another.");
        //        else
        //        {
        //            User user = new User();
        //            user.UserName = model.Email;
        //            user.Password = model.Password;
        //            user.GroupID = ConfigReader.UserGroupIDOfJobSeeker;
        //            user.IsActive = true;

        //            _Context.AddToUsers(user);
        //            _Context.SaveChanges();
        //            return RedirectToAction("Register", new { msg = "True" });
        //        }
        //    }

        //    // If we got this far, something failed, redisplay form
        //    return View(model);
        //}

        /// <summary>
        /// Activate a Company Account or a Job Seeker Account from the provided link in email.
        /// Employer activation is Obsolete in this method.
        /// Instead /Company/Activate method is used for Employer Activation and package subscription
        /// </summary>
        /// <param name="id"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public ActionResult Activate(String id, String key)
        {
            if (id.IsNullOrEmpty() && key.IsNullOrEmpty())
                ModelState.AddModelError(AppConstants.Validation.INVALID_REQUEST, "Invalid Request.");
            else
            {
                Guid activationKey = Guid.Empty;
                Guid.TryParse(key, out activationKey);
                int userID = id.ToInt();
                User user = _Context.Users.Include("Contact").Include("JobSeeker").FirstOrDefault(P => P.ID == userID);
                if (user == null)
                    ModelState.AddModelError(AppConstants.Validation.INVALID_REQUEST, "Invalid Request.");
                else
                {                    
                    if (user.IsActive)
                        ModelState.AddModelError(AppConstants.Validation.INVALID_REQUEST, "This account is already activated.");
                    else
                    {                        
                        ///Check whether this is a JobSeeker or a Employeer
                        ///JobSeeker Checking and Activation                        
                        if (user.JobSeeker != null)
                        {
                            JobSeeker jobSeeker = user.JobSeeker;
                            if (WebUtil.IsGuidEqual(jobSeeker.ActivationKey, activationKey) && !jobSeeker.IsActive)
                            {
                                jobSeeker.IsActive = true;
                                jobSeeker.ModifiedOn = DateTime.Now;
                                user.IsActive = true;
                                _Context.SaveChanges();
                                ViewData[AppConstants.ViewDataKeys.HAS_ACTIVATED] = true;
                                return View();
                            }
                            ModelState.AddModelError(AppConstants.Validation.INVALID_REQUEST, "Invalid Request.");
                        }
                        else
                        {
                            ///Employeer Checking and Activation
                            if (user.Contact != null)
                            {
                                if (WebUtil.IsGuidEqual(user.Contact.Company.ActivationKey, activationKey) && !user.Contact.Company.IsActive)
                                {                                    
                                    var users = from P in _Context.Users where P.Contact.CompanyID == user.Contact.CompanyID select P;
                                    foreach (User companyUser in users)
                                    {
                                        companyUser.IsActive = true;
                                    }
                                    user.Contact.Company.IsActive = true;
                                    _Context.SaveChanges();
                                    ViewData[AppConstants.ViewDataKeys.HAS_ACTIVATED] = true;
                                    return View();
                                }
                                ModelState.AddModelError(AppConstants.Validation.INVALID_REQUEST, "Invalid Request.");
                            }
                        }
                    }
                }
            }
            return View();
        }

        /// <summary>
        /// Shows the generic access denied view if someone tries to access restricted content.
        /// Specially if one user triggers an hacking attempt to access another users data.
        /// </summary>
        /// <returns></returns>
        public ActionResult PermissionDenied()
        {
            return View();
        }	

        #endregion Action Methods

        #region Status Codes
        private static string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // See http://go.microsoft.com/fwlink/?LinkID=177550 for
            // a full list of status codes.
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "User name already exists. Please enter a different user name.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "A user name for that e-mail address already exists. Please enter a different e-mail address.";

                case MembershipCreateStatus.InvalidPassword:
                    return "The password provided is invalid. Please enter a valid password value.";

                case MembershipCreateStatus.InvalidEmail:
                    return "The e-mail address provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "The password retrieval answer provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "The password retrieval question provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidUserName:
                    return "The user name provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.ProviderError:
                    return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                case MembershipCreateStatus.UserRejected:
                    return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                default:
                    return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
            }
        }
        #endregion

        #region Helper Methods
        
        #endregion
    }
}
